home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / comm / misc / 8n1.lha / 8n1.s < prev    next >
Text File  |  1995-09-02  |  90KB  |  1,931 lines

  1. **  $Revision Header Start *****************************************************
  2. **                                                                            **
  3. **  Name       : 8n1.s                                                        **
  4. **  Copyright  : © Copyright 95                                               **
  5. **  Author     : L.Lucius                                                     **
  6. **  Created    : 10 Jul 95                                                    **
  7. **  Version    : 37.12                                                        **
  8. **  Translator : snma 1.99h 16-Aug-95                                         **
  9. **                                                                            **
  10. **  Date       Version  Comment                                               **
  11. **  ---------  -------  ----------------------------------------------------  **
  12. **  02 Sep 95  37.12    Third Aminet release.                                 **
  13. **  02 Sep 95  37.12    Changed DS alignment directives to CNOP directives.   **
  14. **  29 Aug 95  37.12    Added test for QUICK bit in AbortIO routine.          **
  15. **  29 Aug 95  37.12    Removed PC-Relative optimizer option to prevent       **
  16. **                      incorrect conversion to a 68020+ instruction.  This   **
  17. **                      should fix the problems on 68000 machines.            **
  18. **  27 Aug 95  37.12    Added I/O completion status to each command routine   **
  19. **                      and removed unnecessary code from BeginIO routine.    **
  20. **  27 Aug 95  37.12    Re-added list arbitration in cmd_Read.                **
  21. **  24 Aug 95  37.11    Isolated SNMA directives to allow assembly with       **
  22. **                      SAS/C assembler.                                      **
  23. **  23 Aug 95  37.11    Add code to correct bug in NComm.  Define symbol      **
  24. **                      NCOMM and reassemble to get this support.             **
  25. **  23 Aug 95  37.11    Check SOFTINT prior to TBE to keep 8n1 from blocking  **
  26. **                      them.                                                 **
  27. **  23 Aug 95  37.11    Insure that interrupts are enabled prior to checking  **
  28. **                      TBE or RBF interrupts.                                **
  29. **  22 Aug 95  37.11    Turn Handshake on by default to match SerFlags.       **
  30. **  21 Aug 95  37.11    Use current baud and buffer sizes for initializing    **
  31. **                      I/O request instead of default.                       **
  32. **  21 Aug 95  37.11    Set default SERFLAGS during device open.              **
  33. **  20 Aug 95  37.11    Clear SERB_ACTIVE IO_FLAG when I/O has completed.     **
  34. **  20 Aug 95  37.11    Removed unneeded RTS line code added on 04-Aug-95.    **
  35. **  15 Aug 95  37.11    Added line to turn on the DSR bit if needed.          **
  36. **                      Normally commented out.                               **
  37. **  11 Aug 95  37.10    Second Aminet release!                                **
  38. **  10 Aug 95  37.10    Added storage arbitration code to cmd_Read and        **
  39. **                      sdcmd_SetParams.                                      **
  40. **  09 Aug 95  37.10    Removed CIAF_PRTRSEL from PRTMASK to allow usage of   **
  41. **                      ring indicator line.                                  **
  42. **  06 Aug 95  37.10    Added "E-" to SNMAOPT line to prevent "Xref in        **
  43. **                      executable" message.                                  **
  44. **  06 Aug 95  37.10    Changed "8n1Base" to "Base8n1" to make more           **
  45. **                      compatible with other assemblers.                     **
  46. **  06 Aug 95  37.10    Removed ".w" from BTST instructions.                  **
  47. **  06 Aug 95  37.10    Corrected long word test of byte sized field.         **
  48. **  04 Aug 95  37.9     First Aminet Release!                                 **
  49. **  04 Aug 95  37.9     Removed some testing code and prevented unnecessary   **
  50. **                      RTS line updates.                                     **
  51. **  02 Aug 95  37.8     Added the ability to send BREAKs.                     **
  52. **  29 Jul 95  37.7     Rearranged device init data to allow proper display   **
  53. **                      by VERSION command.  (The device base init data had   **
  54. **                      to be within the checksummed area.)                   **
  55. **  28 Jul 95  37.6     When device was opened multiple times in shared       **
  56. **                      mode, GURU occured on first close.                    **
  57. **  22 Jul 95  37.5     Corrected version number.  8n1.i was not being        **
  58. **                      generated correctly.                                  **
  59. **  22 Jul 95  37.5     Incorrect handling of interrupts caused TBE           **
  60. **                      interrupts to be missed.                              **
  61. **  13 Jul 95  37.4     Rewrote the CMD_WRITE and TBE interrupt routines.     **
  62. **                      Lengths of -1 were not being handled properly.        **
  63. **  13 Jul 95  37.3     Rewrote OpenDevice() and CloseDevice() calls to       **
  64. **                      correct several problems.                             **
  65. **  11 Jul 95  37.2     Added "no handshaking" support.                       **
  66. **  11 Jul 95  37.1     Rewrote the RBF interrupt routines and offloaded      **
  67. **                      some of the work to a PORTS interrupt to prevent      **
  68. **                      overruns and add the EOFMODE option.                  **
  69. **  07 Jul 95  37.0     Only tried to remove the 'serial.device' instead of   **
  70. **                      removing the CURRENT owner of the serial resources.   **
  71. **  06 Jul 95  37.0     Invalid size used for GetPrefs() call causing stack   **
  72. **                      overlay.                                              **
  73. **  04 Jul 95  37.0     Set defaults during OpenDevice() instead of assuming  **
  74. **                      values in I/O request are correct.                    **
  75. **  04 Jul 95  37.0     Initial Version                                       **
  76. **                                                                            **
  77. **  $Revision Header End *******************************************************
  78.          ;
  79.          ;        SNMA specific options
  80.          ;
  81.          IFD      SNMA
  82.          ;
  83.          CPU      M68010
  84.          ;
  85.          SNMAOPT  Q,A,M,T,E-
  86.          ;
  87.          INCDIR   "include:"
  88.          ;
  89.          ENDC
  90.          ;
  91.          ;
  92.          ;
  93. DEBUG    SET      0
  94.          ;
  95.          ;
  96.          ;
  97.          SECTION  text,CODE
  98.          ;
  99.          ;
  100.          ;
  101. DEVICES_SERIAL_I_OBSOLETE  EQU      1
  102.          ;
  103.          ;
  104.          ;
  105.          INCLUDE  "exec/lists.i"
  106.          INCLUDE  "exec/memory.i"
  107.          INCLUDE  "exec/resident.i"
  108.          INCLUDE  "exec/devices.i"
  109.          INCLUDE  "exec/execbase.i"
  110.          INCLUDE  "exec/io.i"
  111.          INCLUDE  "exec/ports.i"
  112.          INCLUDE  "exec/errors.i"
  113.          INCLUDE  "exec/initializers.i"
  114.          INCLUDE  "intuition/preferences.i"
  115.          INCLUDE  "devices/timer.i"
  116.          INCLUDE  "devices/serial.i"
  117.          INCLUDE  "hardware/custom.i"
  118.          INCLUDE  "hardware/cia.i"
  119.          INCLUDE  "hardware/intbits.i"
  120.          INCLUDE  "hardware/adkbits.i"
  121.          INCLUDE  "resources/misc.i"
  122.          INCLUDE  "exec/alerts.i"
  123.          INCLUDE  "exec/macros.i"
  124.          INCLUDE  "8n1.i"
  125.          ;
  126.          ;        Define hardware references
  127.          ;
  128.          XREF     _AbsExecBase
  129.          XREF     _custom
  130.          XREF     _intena,_intenar,_intreq,_intreqr
  131.          XREF     _ciab,_ciabpra
  132.          XREF     _serper,_serdat,_serdatr
  133.          XREF     _adkcon,_adkconr
  134.          ;
  135.          ;        Exec Functions
  136.          ;
  137.          XREF     _LVORemDevice,_LVOOpenDevice,_LVOCloseDevice
  138.          XREF     _LVOSupervisor
  139.          XREF     _LVORemove,_LVORemHead,_LVOAddTail
  140.          XREF     _LVOAllocMem,_LVOFreeMem,_LVOCopyMem
  141.          XREF     _LVOReplyMsg
  142.          XREF     _LVOSendIO,_LVOAbortIO
  143.          XREF     _LVODisable,_LVOEnable
  144.          XREF     _LVOFindName
  145.          XREF     _LVOOpenResource
  146.          XREF     _LVOAddIntServer,_LVORemIntServer
  147.          XREF     _LVOSetIntVector
  148.          XREF     _LVOAlert
  149.          XREF     _LVOOldOpenLibrary,_LVOCloseLibrary
  150.          ;
  151.          ;        Misc Resource Functions
  152.          ;
  153.          XREF     _LVOAllocMiscResource,_LVOFreeMiscResource
  154.          ;
  155.          ;        Intuition Functions
  156.          ;
  157.          XREF     _LVOGetPrefs
  158.          ;
  159.          ;        Mask used to get rid of the printer bits.
  160.          ;
  161. PRTMASK  EQU      (CIAF_PRTRPOUT|CIAF_PRTRBUSY)
  162.          ;
  163.          ;        Autovector offsets
  164.          ;
  165. LVL1VEC  EQU      (1-1)*4+$64
  166. LVL5VEC  EQU      (5-1)*4+$64
  167.          ;
  168.          ;        Device base
  169.          ;
  170.          STRUCTURE Base8n1,LIB_SIZE
  171.          UBYTE    vb_SaveDDRA
  172.          UBYTE    vb_SavePRA
  173.          APTR     vb_MiscBase
  174.          APTR     vb_OldLevel1
  175.          APTR     vb_OldLevel5
  176.          ULONG    vb_SegList
  177.          ULONG    vb_DefBaud
  178.          ULONG    vb_DefRBufLen
  179.          ULONG    vb_CurRBuf
  180.          ULONG    vb_CurRBufLen
  181.          ULONG    vb_CurBaud
  182.          UBYTE    vb_SerFlags
  183.          UBYTE    vb_Initialized
  184.          LABEL    sizeof_Base8n1
  185.          ;
  186.          ;
  187.          ;
  188. DISABLE  MACRO
  189.          IFNC     '\1',''
  190.          move.w   #INTF_\1,_intena
  191.          ELSE
  192.          jsr      _LVODisable(a6)
  193.          ENDC
  194.          ENDM
  195.          ;
  196. ENABLE   MACRO
  197.          IFNC     '\1',''
  198.          move.w   #INTF_SETCLR|INTF_\1,_intena
  199.          ELSE
  200.          jsr      _LVOEnable(a6)
  201.          ENDC
  202.          ENDM
  203.          ;
  204.          ;
  205.          ;
  206. PUTDEBUG macro    ;[msg]
  207.          ifge     DEBUG-2
  208.          movem.l  a0/a1/d0/d1,-(sp)
  209.          lea      (.msg\@,pc),a0  ;Point to static format string
  210.          lea      (4*4,sp),a1     ;Point to args
  211.          XREF     DPutFmt
  212.          bsr      DPutFmt
  213.          movem.l  (sp)+,d0/d1/a0/a1
  214.          bra.b    .end\@
  215.  
  216. .msg\@   dc.b     \1,10,0
  217.          CNUL     0,4
  218. .end\@
  219.          endc
  220.          endm
  221.          ;
  222.          ;
  223.          ;
  224. DEBUG1   MACRO
  225.          IFEQ      DEBUG-1
  226.          XREF     _SendText
  227.          move.l   \2,-(sp)
  228.          pea.l    debug1s\@$
  229.          pea.l    Name
  230.          jsr      _SendText(pc)
  231.          lea.l    12(sp),sp
  232.          bra.b    debug1x\@$
  233. debug1s\@$:
  234.          dc.b     \1,0
  235.          CNOP     0,2
  236. debug1x\@$:
  237.          ENDC
  238.          ENDM
  239. DEBUG0   MACRO
  240.          XREF     _SendText
  241.          pea.l    debug1s\@$
  242.          pea.l    Name
  243.          jsr      _SendText(pc)
  244.          lea.l    8(sp),sp
  245.          bra.b    debug1x\@$
  246. debug1s\@$:
  247.          dc.b     \1,0
  248. debug1x\@$:
  249.          ENDM
  250.  
  251. DEBUGIO  MACRO
  252.          IFEQ     DEBUG-1
  253.          lea.l    \1,a0
  254.          jsr      printIO
  255.          ENDC
  256.          ENDM
  257.          ;
  258.          ;
  259.          ;
  260. Start:
  261.          moveq    #-1,d0                              ; set return code
  262.          rts                                          ; return
  263.          ;
  264.          ;        RamLib looks for this romtag
  265.          ;
  266. ROMTag   DC.W     RTC_MATCHWORD                       ; RT_MATCHWORD
  267.          DC.L     ROMTag                              ; RT_MATCHTAG
  268.          DC.L     ENDTag                              ; RT_ENDSKIP
  269.          DC.B     RTF_AUTOINIT                        ; RT_FLAGS
  270.          DC.B     VERSION                             ; RT_VERSION
  271.          DC.B     NT_DEVICE                           ; RT_TYPE
  272.          DC.B     0                                   ; RT_PRI
  273.          DC.L     Name                                ; RT_NAME
  274.          DC.L     IdString                            ; RT_IDSTRING
  275.          DC.L     Init                                ; RT_INIT
  276.          ;
  277.          ;        Perform device initialization
  278.          ;
  279. InitRoutine:
  280.          exg      d0,a0                               ; swap seglist and base
  281.          move.l   d0,vb_SegList(a0)                   ; store seglist in base
  282.          move.l   a6,SysBase                          ; store in global storage
  283.          exg      a0,d0                               ; swap them back
  284.          rts                                          ; return
  285.          ;
  286.          ;
  287.          ;
  288. dev_Open:
  289.          DEBUG1   "Devstart %lx",#Start
  290.          move.l   a5,-(sp)                            ; save registers
  291.          movea.l  a6,a5                               ; save base
  292.          movea.l  SysBase(pc),a6                      ; get ExecBase
  293.          ;
  294.          tst.l    d0                                  ; unit 0 specified?
  295.          bne.b    50$                                 ; nope, error (who cares?)
  296.          ;
  297.          tst.w    LIB_OPENCNT(a5)                     ; currently open?
  298.          bne.b    10$                                 ; yep, go process
  299.          ;
  300.          move.b   IO_SERFLAGS(a1),vb_SerFlags(a5)     ; save flags
  301.          ;
  302.          tst.b    vb_Initialized(a5)                  ; already initialized?
  303.          bne.b    40$                                 ; yep, skip initialization
  304.          ;
  305.          bsr      initResources                       ; go alloc resources
  306.          tst.l    d0                                  ; initialized?
  307.          bne.b    50$                                 ; nope, error
  308.          ;
  309.          bra.b    40$                                 ; go exit
  310.          ;
  311. 10$      moveq    #SerErr_DevBusy,d0                  ; preset error status
  312.          btst.b   #SERB_SHARED,vb_SerFlags(a5)        ; opened shared?
  313.          beq.b    50$                                 ; nope, error
  314.          btst.b   #SERB_SHARED,IO_SERFLAGS(a1)        ; requesting shared?
  315.          beq.b    50$                                 ; nope, error
  316.          ;
  317.          ;        Initialize I/O request
  318.          ;
  319. 40$      moveq    #8,d0                               ; get char size
  320.          move.b   d0,IO_READLEN(a1)                   ; set read length
  321.          move.b   d0,IO_WRITELEN(a1)                  ; set write length
  322.          moveq    #1,d0                               ; get stop bits
  323.          move.b   d0,IO_STOPBITS(a1)                  ; set stop bits
  324.          ori.b    #SERF_XDISABLED|SERF_RAD_BOOGIE|SERF_QUEUEDBRK|SERF_7WIRE,IO_SERFLAGS(a1) ;flags
  325.          andi.b   #~(SERF_PARTY_ODD|SERF_PARTY_ON),IO_SERFLAGS(a1) ; not used
  326.          move.l   vb_CurBaud(a5),IO_BAUD(a1)          ; set baud
  327.          move.l   vb_CurRBufLen(a5),IO_RBUFLEN(a1)    ; set read buffer length
  328.          ;
  329.          addq.w   #1,LIB_OPENCNT(a5)                  ; incr open count
  330.          bclr.b   #LIBB_DELEXP,LIB_FLAGS(a5)          ; clear expunge bit
  331.          moveq    #0,d0                               ; no error
  332.          ;
  333. 50$      move.b   d0,IO_ERROR(a1)                     ; store error code
  334.          movea.l  a5,a6                               ; restore base
  335.          move.l   (sp)+,a5                            ; restore registers
  336.          rts                                          ; return
  337.          ;
  338.          ;        Attempt to allocate one of the serial resources.
  339.          ;
  340. allocResource:
  341.          move.l   a6,-(sp)                            ; save base pointer
  342.          move.l   d0,-(sp)                            ; save unit
  343.          lea.l    Name(pc),a1                         ; get lock name
  344.          move.l   vb_MiscBase(a5),a6                  ; get MiscBase
  345.          jsr      _LVOAllocMiscResource(a6)           ; go allocate it
  346.          tst.l    d0                                  ; did we get it?
  347.          beq.b    20$                                 ; yep, branch
  348.          ;
  349.          ;        It's in use, so we try to locate the device using the string
  350.          ;        returned and attempt to remove it.
  351.          ;
  352.          movea.l  SysBase(pc),a6                      ; get ExecBase
  353.          ;
  354.          movea.l  d0,a1                               ; get ptr to serial name
  355.          lea.l    DeviceList(a6),a0                   ; get ptr to device list
  356.          jsr      _LVOFindName(a6)                    ; go find it
  357.          tst.l    d0                                  ; found?
  358.          beq.b    10$                                 ; nope, branch
  359.          ;
  360.          movea.l  d0,a1                               ; xfer device ptr
  361.          jsr      _LVORemDevice(a6)                   ; remove it
  362.          ;
  363.          ;        We then retry the allocate.
  364.          ;
  365. 10$      move.l   (sp),d0                             ; get unit
  366.          lea.l    Name(pc),a1                         ; get lock name
  367.          movea.l  vb_MiscBase(a5),a6                  ; get MiscBase
  368.          jsr      _LVOAllocMiscResource(a6)           ; go allocate it
  369.          ;
  370. 20$      addq.l   #4,sp                               ; restore stack ptr
  371.          movea.l  (sp)+,a6                            ; restore base ptr
  372.          rts                                          ; return
  373.          ;
  374.          ;
  375.          ;
  376. initResources:
  377.          move.l   a1,-(sp)                            ; save register
  378.          ;
  379.          lea.l    miscresource(pc),a1                 ; ptr to resource name
  380.          jsr      _LVOOpenResource(a6)                ; go open it
  381.          move.l   d0,vb_MiscBase(a5)                  ; save base
  382.          ;
  383.          moveq    #MR_SERIALPORT,d0                   ; set unit number
  384.          bsr.b    allocResource                       ; go allocate it
  385.          tst.l    d0                                  ; did we get it?
  386.          bne.b    20$                                 ; nope, error
  387.          ;
  388.          moveq    #MR_SERIALBITS,d0                   ; set unit number
  389.          bsr.b    allocResource                       ; go allocate it
  390.          tst.l    d0                                  ; did we get it?
  391.          bne.b    10$                                 ; nope, error
  392.          ;
  393.          bsr      getPrefs                            ; get default preferences
  394.          tst.l    d0                                  ; got 'em?
  395.          beq.b    30$                                 ; yep, branch
  396.          ;
  397.          moveq    #MR_SERIALPORT,d0                   ; set unit
  398.          movea.l  vb_MiscBase(a5),a6                  ; get MiscBase
  399.          jsr      _LVOFreeMiscResource(a6)            ; release the resource
  400.          ;
  401. 10$      moveq    #MR_SERIALPORT,d0                   ; set unit
  402.          movea.l  vb_MiscBase(a5),a6                  ; get MiscBase
  403.          jsr      _LVOFreeMiscResource(a6)            ; release the resource
  404.          movea.l  SysBase(pc),a6                      ; restore ExecBase
  405.          ;
  406. 20$      moveq    #SerErr_DevBusy,d0                  ; set error status
  407.          bra      40$                                 ; go return
  408.          ;
  409. 30$      moveq    #0,d1                               ; clear flags
  410.          moveq    #UNIT_VBLANK,d0                     ; set unit
  411.          lea.l    timerReq(pc),a1                     ; ptr to timer request
  412.          lea.l    timerdevice(pc),a0                  ; ptr to device name
  413.          jsr      _LVOOpenDevice(a6)                  ; go open it
  414.          ;
  415.          DISABLE                                      ; disable interrupts
  416.          ;
  417.          lea.l    _ciab,a1                            ; get ptr to ciab
  418.          move.b   ciaddra(a1),vb_SaveDDRA(a5)         ; save DDR value
  419.          andi.b   #PRTMASK,ciaddra(a1)                ; make serial bits input
  420.          move.b   ciapra(a1),vb_SavePRA(a5)           ; save PR value
  421.          ori.b    #CIAF_COMDTR|CIAF_COMRTS,ciaddra(a1) ; make DTR/RTS output
  422.          andi.b   #CIAF_COMCTS|CIAF_COMDSR|PRTMASK,ciapra(a1) ; make CTS/DSR input
  423.          andi.b   #CIAF_COMDTR|CIAF_COMRTS|PRTMASK,ciaddra(a1) ; turn on DTR/RTS
  424.          ;
  425.          moveq    #INTB_PORTS,d0                      ; get interrupt number
  426.          lea.l    VBInterrupt(pc),a1                  ; get interrupt ptr
  427.          jsr      _LVOAddIntServer(a6)                ; add it to the list
  428.          ;
  429.          bsr      getVBR                              ; get vector base (in A0)
  430.          ;
  431.          move.l   LVL1VEC(a0),vb_OldLevel1(a5)        ; save original vector
  432.          lea.l    level1(pc),a1                       ; get new vector ptr
  433.          move.l   a1,LVL1VEC(a0)                      ; set new vector
  434.          ;
  435.          move.l   LVL5VEC(a0),vb_OldLevel5(a5)        ; save original vector
  436.          lea.l    level5(pc),a1                       ; get new vector ptr
  437.          move.l   a1,LVL5VEC(a0)                      ; set new vector
  438.          ;
  439.          lea.l    _custom,a1                          ; get ptr to custom chips
  440.          move.w   #INTF_RBF|INTF_TBE,intreq(a1)       ; clear pending interrupts
  441.          move.w   #INTF_SETCLR|INTF_RBF|INTF_TBE,intena(a1) ; enable RBF & TBE
  442.          ;
  443.          addq.b   #1,vb_Initialized(a5)               ; set flag
  444.          moveq    #0,d0                               ; set good status
  445.          ;
  446.          ENABLE                                       ; enable interrupts
  447.          ;
  448. 40$      movea.l  (sp)+,a1                            ; restore register
  449.          rts                                          ; return
  450.          ;
  451.          ;        Get system preferences
  452.          ;
  453. getPrefs:
  454.          move.l   a1,-(sp)                            ; save registers
  455.          ;
  456.          lea.l    intuitlib(pc),a1                    ; ptr to library name
  457.          jsr      _LVOOldOpenLibrary(a6)              ; go open it (any version)
  458.          movea.l  d0,a6                               ; get intuition base
  459.          ;
  460.          move.l   #(pf_SerParShk+3)&$fffffffc,d0      ; size we need (aligned)
  461.          suba.l   d0,sp                               ; reserve space
  462.          ;
  463.          movea.l  sp,a0                               ; set data area ptr
  464.          jsr      _LVOGetPrefs(a6)                    ; get preferences
  465.          ;
  466.          movea.l  a6,a1                               ; get intuition base
  467.          movea.l  SysBase(pc),a6                      ; restore ExecBase
  468.          jsr      _LVOCloseLibrary(a6)                ; close it
  469.          ;
  470.          moveq    #$0f,d1                             ; set mask
  471.          and.b    pf_SerStopBuf(sp),d1                ; get bufsize index
  472.          addq.l   #8,d1                               ; calc shift value
  473.          moveq    #2,d0                               ; get 1<<1
  474.          lsl.l    d1,d0                               ; get default bufsize
  475.          move.l   d0,vb_DefRBufLen(a5)                ; and store
  476.          ;
  477.          moveq    #0,d1                               ; clear upper half
  478.          move.w   pf_BaudRate(sp),d1                  ; get baud rate
  479.          add.l    d1,d1                               ; generate offset
  480.          move.w   baudTable(pc,d1.w),d1               ; get default baud
  481.          move.l   d1,vb_DefBaud(a5)                   ; and store
  482.          ;
  483.          bsr      internalReset                       ; go init baud and buffer
  484.          ;
  485.          lea.l    (pf_SerParShk+3)&$fffffffc(sp),sp   ; restore stack
  486.          movea.l  (sp)+,a1                            ; restore registers
  487.          rts                                          ; return ( status in D0 )
  488.          ;
  489.          ;        Preferences baud lookup table
  490.          ;
  491. baudTable:
  492.          dc.w     112,300,1200,2400,4800,9600,19200,31250
  493.          ;
  494.          ;        Set exception vectors
  495.          ;
  496. getVBR:
  497.          move.l   a5,-(sp)                            ; save registers
  498.          suba.l   a0,a0                               ; ptr to vector base (68000)
  499.          btst.b   #AFB_68010,AttnFlags+1(a6)          ; 68010 or higher?
  500.          beq.b    10$                                 ; nope, go set vector
  501.          lea.l    20$(pc),a5                          ; ptr to routine
  502.          jsr      _LVOSupervisor(a6)                  ; get into supervisor state
  503. 10$      movea.l  (sp)+,a5                            ; restore register
  504.          rts                                          ; return
  505. 20$      movec.l  vbr,a0                              ; get vector base
  506.          rte                                          ; return
  507.          ;
  508.          ;
  509.          ;
  510. freeResources:
  511.          move.l   a1,-(sp)                            ; save registers
  512.          ;
  513.          DISABLE                                      ; disable interrupts
  514.          ;
  515.          bsr      getVBR                              ; get vector base (in A0)
  516.          ;
  517.          moveq    #1,d0                               ; set not restored code
  518.          ;
  519.          lea.l    level1(pc),a1                       ; get our vector ptr
  520.          cmpa.l   LVL1VEC(a0),a1                      ; do they match?
  521.          bne      10$                                 ; nope, can't restore
  522.          ;
  523.          lea.l    level5(pc),a1                       ; get our vector ptr
  524.          cmpa.l   LVL5VEC(a0),a1                      ; do they match?
  525.          bne      10$                                 ; nope, can't restore
  526.          ;
  527.          move.l   vb_OldLevel1(a5),LVL1VEC(a0)        ; restore original vector
  528.          move.l   vb_OldLevel5(a5),LVL5VEC(a0)        ; restore original vector
  529.          ;
  530.          moveq    #INTB_PORTS,d0                      ; get interrupt number
  531.          lea.l    VBInterrupt(pc),a1                  ; get interrupt ptr
  532.          jsr      _LVORemIntServer(a6)                ; remove it from the list
  533.          ;
  534.          move.w   #INTF_RBF|INTF_TBE,d0               ; indicate serial interrupts
  535.          move.w   d0,_intena                          ; disable interrupts
  536.          move.w   d0,_intreq                          ; clear pending interrupts
  537.          ;
  538.          bsr      freeBuf                             ; free allocated buffers
  539.          ;
  540.          lea.l    _ciab,a0                            ; get pointer to ciab
  541.          move.b   ciaddra(a0),d0                      ; get DDR value
  542.          andi.b   #PRTMASK,d0                         ; save printer bits
  543.          ori.b    #~PRTMASK,d0                        ; set serial bits to output
  544.          move.b   d0,ciaddra(a0)                      ; store value
  545.          ;
  546.          move.b   ciapra(a0),d0                       ; get PR value
  547.          andi.b   #PRTMASK,d0                         ; mask out serial bits
  548.          move.b   vb_SavePRA(a5),d1                   ; get saved value
  549.          andi.b   #~PRTMASK,d1                        ; mask out printer bits
  550.          or.b     d1,d0                               ; combine the two
  551.          move.b   d0,ciapra(a0)                       ; and store
  552.          ;
  553.          move.b   ciaddra(a0),d0                      ; get DDR value
  554.          andi.b   #PRTMASK,d0                         ; mask out serial bits
  555.          move.b   vb_SaveDDRA(a5),d1                  ; get saved value
  556.          andi.b   #~PRTMASK,d1                        ; mask out printer bits
  557.          or.b     d1,d0                               ; combine the two
  558.          move.b   d0,ciaddra(a0)                      ; and store
  559.          ;
  560.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  561.          jsr      _LVOCloseDevice(a6)                 ; go close it
  562.          ;
  563.          movea.l  vb_MiscBase(a5),a6                  ; get MiscBase
  564.          moveq    #MR_SERIALBITS,d0                   ; set unit
  565.          jsr      _LVOFreeMiscResource(a6)            ; release the resource
  566.          ;
  567.          moveq    #MR_SERIALPORT,d0                   ; set unit
  568.          jsr      _LVOFreeMiscResource(a6)            ; release the resource
  569.          movea.l  SysBase(pc),a6                      ; restore ExecBase
  570.          ;
  571.          ENABLE                                       ; enable interrupts
  572.          ;
  573.          subq.b   #1,vb_Initialized(a5)               ; clear flag
  574.          moveq    #0,d0                               ; free up everything
  575.          ;
  576. 10$      movea.l  (sp)+,a1                            ; restore registers
  577.          rts                                          ; return
  578.          ;
  579.          ;        Device Close routine
  580.          ;
  581. dev_Close:
  582.          ;
  583.          moveq    #-1,d0                              ; invalidate
  584.          move.l   d0,IO_DEVICE(a1)                    ;   device
  585.          ;
  586.          subq.w   #1,LIB_OPENCNT(a6)                  ; decr open count
  587.          bne.b    dev_Null                            ; still open? yep, branch
  588.          ;
  589.          move.l   a5,-(sp)                            ; save registers
  590.          movea.l  a6,a5                               ; save base
  591.          movea.l  SysBase(pc),a6                      ; get ExecBase
  592.          ;
  593.          bsr      freeResources                       ; free allocated resources
  594.          ;
  595.          movea.l  a5,a6                               ; restore base
  596.          movea.l  (sp)+,a5                            ; restore registers
  597.          ;
  598.          tst.l    d0                                  ; freed?
  599.          bne.b    dev_Null                            ; nope, can't expunge, exit
  600.          ;
  601.          clr.b    vb_SerFlags(a6)                     ; clear flags
  602.          ;
  603.          btst.b   #LIBB_DELEXP,LIB_FLAGS(a6)          ; delayed expunge set?
  604.          beq.b    dev_Null                            ; nope, go exit
  605.          ;
  606.          ;        Device Expunge routine (also fall through from dev_Close)
  607.          ;
  608. dev_Expunge:
  609.          bset.b   #LIBB_DELEXP,LIB_FLAGS(a6)          ; Set expunge flag
  610.          tst.w    LIB_OPENCNT(a6)                     ; currently open?
  611.          bne.b    dev_Null                            ; yep, so just exit
  612.          ;
  613.          move.l   vb_SegList(a6),d0                   ; get seglist ptr
  614.          movem.l  d0/a5/a6,-(sp)                      ; save registers (save D0!)
  615.          ;
  616.          movea.l  a6,a5                               ; save base
  617.          movea.l  SysBase(pc),a6                      ; get ExecBase
  618.          movea.l  a5,a1                               ; get base
  619.          jsr      _LVORemove(a6)                      ; Remove it
  620.          ;
  621.          movea.l  a5,a1                               ; get base
  622.          moveq    #0,d0                               ; clear work
  623.          move.w   LIB_NEGSIZE(a5),d0                  ; calculate
  624.          suba.w   d0,a1                               ;   memory address
  625.          add.w    LIB_POSSIZE(a5),d0                  ;     and size
  626.          jsr      _LVOFreeMem(a6)                     ; free it
  627.          ;
  628.          movem.l  (sp)+,d0/a5/a6                      ; restore registers
  629.          rts                                          ; return (seglist in D0!)
  630.          ;
  631.          ;        Device "ExtFunc" routine
  632.          ;
  633. dev_Null:
  634.          moveq    #0,d0                               ; set return code
  635.          rts                                          ; return
  636.          ;
  637.          ;
  638.          ;
  639.          IFEQ     DEBUG-1
  640. printIO:
  641.          movem.l  d0-d7/a0-a6,-(sp)
  642.          addq.l   #1,ioctr
  643.          move.l   ioctr,-(sp)
  644.          move.l   a1,-(sp)
  645.          move.l   a0,-(sp)
  646.          pea.l    0$
  647.          pea.l    Name
  648.          DISABLE  TBE|INTF_PORTS
  649.          jsr      _SendText(pc)
  650.          ENABLE   TBE|INTF_PORTS
  651.          lea.l    20(sp),sp
  652.  
  653.          moveq    #0,d0
  654.          move.w   IO_COMMAND(a1),d0
  655.          move.l   d0,-(sp)
  656.          move.l   MN_REPLYPORT(a1),-(sp)
  657.          moveq    #0,d0
  658.          move.b   LN_TYPE(a1),d0
  659.          move.l   d0,-(sp)
  660.          pea.l    1$
  661.          pea.l    Name
  662.          DISABLE  TBE|INTF_PORTS
  663.          jsr      _SendText(pc)
  664.          ENABLE   TBE|INTF_PORTS
  665.          lea.l    20(sp),sp
  666.  
  667.          move.l   IO_LENGTH(a1),-(sp)
  668.          moveq    #0,d0
  669.          move.b   IO_ERROR(a1),d0
  670.          move.l   d0,-(sp)
  671.          move.b   IO_FLAGS(a1),d0
  672.          move.l   d0,-(sp)
  673.          pea.l    2$
  674.          pea.l    Name
  675.          DISABLE  TBE|INTF_PORTS
  676.          jsr      _SendText(pc)
  677.          ENABLE   TBE|INTF_PORTS
  678.          lea.l    20(sp),sp
  679.  
  680.          move.l   IO_EXTFLAGS(a1),-(sp)
  681.          move.l   IO_RBUFLEN(a1),-(sp)
  682.          move.l   IO_ACTUAL(a1),-(sp)
  683.          pea.l    3$
  684.          pea.l    Name
  685.          DISABLE  TBE|INTF_PORTS
  686.          jsr      _SendText(pc)
  687.          ENABLE   TBE|INTF_PORTS
  688.          lea.l    20(sp),sp
  689.  
  690.          moveq    #0,d0
  691.          move.b   IO_WRITELEN(a1),d0
  692.          move.l   d0,-(sp)
  693.          move.b   IO_READLEN(a1),d0
  694.          move.l   d0,-(sp)
  695.          move.l   IO_BAUD(a1),-(sp)
  696.          pea.l    4$
  697.          pea.l    Name
  698.          DISABLE  TBE|INTF_PORTS
  699.          jsr      _SendText(pc)
  700.          ENABLE   TBE|INTF_PORTS
  701.          lea.l    20(sp),sp
  702.  
  703.          moveq    #0,d0
  704.          move.w   IO_STATUS(a1),d0
  705.          move.l   d0,-(sp)
  706.          moveq    #0,d0
  707.          move.b   IO_SERFLAGS(a1),d0
  708.          move.l   d0,-(sp)
  709.          move.b   IO_STOPBITS(a1),d0
  710.          move.l   d0,-(sp)
  711.          pea.l    5$
  712.          pea.l    Name
  713.          DISABLE  TBE|INTF_PORTS
  714.          jsr      _SendText(pc)
  715.          ENABLE   TBE|INTF_PORTS
  716.          lea.l    20(sp),sp
  717.          movem.l  (sp)+,d0-d7/a0-a6
  718.          rts
  719. 0$       dc.b     '%ls - I/O     %8lx, Cnt = %ld',0
  720. 1$       DC.B     'Type    %8ld     ReplyPort %8lx    Command  %8ld',0
  721. 2$       DC.B     'Flags   %8lx     Error     %8ld    Length   %8ld',0
  722. 3$       DC.B     'Actual  %8ld     RBufLen   %8ld    ExtFlags %8lx',0
  723. 4$       DC.B     'Baud    %8ld     ReadLen   %8ld    WriteLen %8ld',0
  724. 5$       DC.B     'StopBit %8ld     SerFlags  %8lx    Status   %8lx',0
  725.          ;
  726.          ;
  727.          ;
  728. abortIOs dc.b     'Abort Start',0
  729. abortIOe dc.b     'Abort End',0
  730. abortIOa dc.b     'Aborting',0
  731. beginIOs dc.b     'Begin Start',0
  732. beginIOe dc.b     'Begin End',0
  733. openIO   dc.b     'Open IO',0
  734. replyIO  dc.b     'replyIO',0
  735.          ds.l     0
  736. ioctr    dc.l     0
  737.          ENDC
  738.          ;
  739. cmdTable dc.w     cmd_Invalid-cmdTable                ; CMD_INVALID
  740.          dc.w     cmd_Reset-cmdTable                  ; CMD_RESET
  741.          dc.w     cmd_Read-cmdTable                   ; CMD_READ
  742.          dc.w     cmd_Write-cmdTable                  ; CMD_WRITE
  743.          dc.w     cmd_Invalid-cmdTable                ; CMD_UPDATE
  744.          dc.w     cmd_Clear-cmdTable                  ; CMD_CLEAR
  745.          dc.w     cmd_Invalid-cmdTable                ; CMD_STOP
  746.          dc.w     cmd_Invalid-cmdTable                ; CMD_START
  747.          dc.w     cmd_Flush-cmdTable                  ; CMD_FLUSH
  748.          dc.w     sdcmd_Query-cmdTable                ; SDCMD_QUERY
  749.          dc.w     sdcmd_Break-cmdTable                ; SDCMD_BREAK
  750. endTable dc.w     sdcmd_SetParams-cmdTable            ; SDCMD_SETPARAMS
  751.          ;
  752.          ;        Device BeginIO routine
  753.          ;
  754. dev_BeginIO:
  755.          move.l   a5,-(sp)                            ; save register
  756.          movea.l  a6,a5                               ; save base
  757.          movea.l  SysBase(pc),a6                      ; get ExecBase
  758.          DEBUGIO  beginIOs
  759.          ;
  760.          move.b   #NT_MESSAGE,LN_TYPE(a1)             ; set type
  761.          clr.b    IO_ERROR(a1)                        ; clear error
  762.          ;
  763.          andi.b   #~(IOSERF_QUEUED|IOSERF_ACTIVE),IO_FLAGS(a1) ; clear flags
  764.          ;
  765.          move.w   IO_COMMAND(a1),d0                   ; get command
  766.          add.w    d0,d0                               ; multiply by 2
  767.          cmpi.w   #endTable-cmdTable,d0               ; in range?
  768.          bhi.b    30$                                 ; nope, error
  769.          ;
  770.          move.w   cmdTable(pc,d0.w),d0                ; get routine offset
  771.          jsr      cmdTable(pc,d0.w)                   ; go do it
  772.          tst.l    d0                                  ; I/O completed?
  773.          bne.b    19$                                 ; nope, go return
  774.          ;
  775. 10$      DEBUGIO  beginIOe
  776.          btst.b   #IOB_QUICK,IO_FLAGS(a1)             ; need to reply?
  777.          bne.b    20$                                 ; nope, branch
  778. 15$      jsr      _LVOReplyMsg(a6)                    ; send it back
  779.          ;
  780. 19$      bclr.b   #IOB_QUICK,IO_FLAGS(a1)             ; clear quick bit
  781. 20$      movea.l  a5,a6                               ; restore base
  782.          movea.l  (sp)+,a5                            ; restore register
  783.          rts                                          ; return
  784.          ;
  785. 30$      move.b   #IOERR_NOCMD,IO_ERROR(a1)           ; invalid command
  786.          bra.b    10$                                 ; branch
  787.          ;
  788.          ;        Device AbortIO routine
  789.          ;
  790. dev_AbortIO:
  791.          move.l   a5,-(sp)                            ; save registers
  792.          movea.l  a6,a5                               ; save base
  793.          movea.l  SysBase(pc),a6                      ; get ExecBase
  794.          DEBUGIO  abortIOs
  795.          ;
  796.          DISABLE                                      ; disable interrupts
  797.          ;
  798.          btst.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; queued request?
  799.          bne.b    40$                                 ; yep, branch
  800.          ;
  801.          btst.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; active request?
  802.          beq.b    10$                                 ; nope, just exit
  803.          ;
  804.          move.w   IO_COMMAND(a1),d0                   ; get command
  805.          subq.w   #CMD_READ,d0                        ; was it a read?
  806.          beq.b    20$                                 ; yep, go process
  807.          ;
  808.          subq.w   #CMD_WRITE-CMD_READ,d0              ; was it a write?
  809.          beq.b    30$                                 ; yep, go process
  810.          ;
  811.          subq.w   #SDCMD_BREAK-CMD_WRITE,d0           ; was it a break?
  812.          beq.b    30$                                 ; yep, go process
  813.          ;
  814.          ;        Fall through or enter from below
  815.          ;
  816. 10$      ENABLE                                       ; enable ints and return
  817. 15$      movea.l  a5,a6                               ; restore base
  818.          movea.l  (sp)+,a5                            ; restore registers
  819.          rts                                          ; return
  820.          ;
  821.          ;        Abort an active read request
  822.          ;
  823. 20$      clr.l    cr_IOReq                            ; no longer active
  824.          bra.b    50$                                 ; go set flags
  825.          ;
  826.          ;        Abort an active write request
  827.          ;
  828. 30$      clr.l    cw_Length                           ; no longer active
  829.          clr.l    cw_IOReq                            ; no longer active
  830.          move.l   cw_Buffer(pc),d0                    ; get buffer ptr
  831.          sub.l    IO_DATA(a1),d0                      ; calc number of bytes xfer'd
  832.          move.l   d0,IO_ACTUAL(a1)                    ; store
  833.          ;
  834.          ;        Force a TBE interrupt to get the next write going.
  835.          ;
  836.          move.w   #INTF_SETCLR|INTF_TBE,_intreq       ; make TBE pending
  837.          bra.b    50$                                 ; go set flags
  838.          ;
  839.          ;        Remove I/O from queue.
  840.          ;
  841. 40$      move.l   a1,-(sp)                            ; save ptr
  842.          jsr      _LVORemove(a6)                      ; remove it
  843.          movea.l  (sp)+,a1                            ; restore ptr
  844.          ;
  845.          ;        Set error and return I/O
  846.          ;
  847. 50$      move.b   #IOERR_ABORTED,IO_ERROR(a1)         ; set error code
  848.          move.b   IO_FLAGS(a1),d1                     ; get flags
  849.          bset.b   #IOSERB_ABORT,d1                    ; set abort flag
  850.          andi.b   #~(IOSERF_QUEUED|IOSERF_ACTIVE),d1  ; clear flags
  851.          DEBUGIO  abortIOe
  852.          btst.b   #IOB_QUICK,d1                       ; need to reply?
  853.          bne.b    10$                                 ; nope, branch
  854.          jsr      _LVOReplyMsg(a6)                    ; send it back
  855.          bra.b    10$                                 ; branch to return
  856.          ;
  857.          ;        Abort all active/queued commands and reset internal state
  858.          ;
  859. cmd_Reset:
  860.          move.l   a1,-(sp)                            ; save I/O request
  861.          bsr.b    cmd_Flush                           ; go abort queued requests
  862.          ;
  863.          DISABLE                                      ; disable interrupts
  864.          ;
  865.          ;        This must follow the DISABLE
  866.          ;
  867.          exg      a5,a6                               ; exchange base and ExecBase
  868.          ;
  869.          move.l   cr_IOReq(pc),d0                     ; active read?
  870.          beq.b    10$                                 ; nope, branch
  871.          movea.l  d0,a1                               ; get I/O request
  872.          bsr      dev_AbortIO                         ; go abort it
  873.          ;
  874.          ;
  875.          ;
  876. 10$      move.l   cw_IOReq(pc),d0                     ; active write?
  877.          beq.b    20$                                 ; nope, branch
  878.          movea.l  d0,a1                               ; get I/O request
  879.          bsr      dev_AbortIO                         ; go abort it
  880.          ;
  881. 20$      exg      a5,a6                               ; restore base and ExecBase
  882.          movea.l  (sp)+,a1                            ; restore I/O request
  883.          moveq    #8,d0                               ; get char size
  884.          move.b   d0,IO_READLEN(a1)                   ; set read length
  885.          move.b   d0,IO_WRITELEN(a1)                  ; set write length
  886.          moveq    #1,d0                               ; get stop bits
  887.          move.b   d0,IO_STOPBITS(a1)                  ; set stop bits
  888.          move.l   vb_DefBaud(a5),IO_BAUD(a1)          ; set to default baud
  889.          move.l   vb_DefRBufLen(a5),IO_RBUFLEN(a1)    ; set to default buflen
  890.          bsr      internalReset                       ; go set/verify parameters
  891.          move.b   d0,IO_ERROR(a1)                     ; set error code
  892.          ENABLE                                       ; enable interrupts
  893.          ;
  894.          ;        Set RC and return
  895.          ;
  896.          moveq    #0,d0                               ; I/O complete
  897.          rts                                          ; return
  898.          ;
  899.          ;        Abort all "queued" requests, leaving all active alone.
  900.          ;
  901. cmd_Flush:
  902.          movem.l  a1/a2,-(sp)                         ; save registers
  903.          DISABLE                                      ; disable interrupts
  904.          ;
  905.          ;        Abort all queued read requests.
  906.          ;
  907.          lea.l    readQ(pc),a2                        ; get ptr to read queue
  908.          bsr.b    20$                                 ; branch to abort
  909.          ;
  910.          ;        Abort all queued write requests.
  911.          ;
  912.          lea.l    writeQ(pc),a2                       ; get ptr to write queue
  913.          bsr.b    20$                                 ; branch to abort
  914.          ;
  915.          ;        Enable, restore, and return to caller
  916.          ;
  917.          ENABLE                                       ; enable interrupts
  918.          movem.l  (sp)+,a1/a2                         ; restore registers
  919.          ;
  920.          ;        Set RC and return
  921.          ;
  922.          moveq    #0,d0                               ; I/O complete
  923.          ;
  924.          ;        !!!NOTE!!!  In a mad attempt to save 2 bytes, this RTS is used
  925.          ;        by the subroutine below.  Why waste 'em?  B-)
  926.          ;
  927. 10$      rts                                          ; return ( used below too!! )
  928.          ;
  929.          ;        Subroutine to remove and reply each I/O request.
  930.          ;
  931. 20$      movea.l  a2,a0                               ; get list ptr
  932.          jsr      _LVORemHead(a6)                     ; get I/O request
  933.          tst.l    d0                                  ; end of list?
  934.          beq.b    10$                                 ; yep, branch to return
  935.          ;
  936.          movea.l  d0,a1                               ; get I/O request
  937.          bclr.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; no longer queued
  938.          moveq    #IOERR_ABORTED,d0                   ; indicate aborted
  939.          move.b   d0,IO_ERROR(a1)                     ; store status
  940.          ;
  941.          jsr      _LVOReplyMsg(a6)                    ; send it back
  942.          bra.b    20$                                 ; continue with next
  943.          ;
  944.          ;        Process a CMD_READ request.
  945.          ;
  946. cmd_Read:
  947.          ;
  948.          ;        Zero length requests just get returned.
  949.          ;
  950.          clr.l    IO_ACTUAL(a1)                       ; clear bytes read
  951.          move.l   IO_LENGTH(a1),d0                    ; get length and test
  952.          beq.b    20$                                 ; yep, leave
  953.          ;
  954.          ;        This can be used to circumvent a bug in NComm 3.0 which
  955.          ;        references the buffer even when there was nothing read.
  956.          ;
  957.          IFD      NCOMM
  958.          move.l   IO_DATA(A1),a0                      ; get data pointer
  959.          clr.b    (a0)                                ; clear first byte in buffer
  960.          ENDC
  961.          ;
  962.          ;        The disable counter works just like exec's TDNestCnt field.  It's
  963.          ;        initialized to -1.  After incrementing, if it is 0, then we
  964.          ;        can attempt to process this request immediately.  If it's > 0,
  965.          ;        then we're already disabled and we must queue this request.
  966.          ;
  967.          addq.b   #1,disableRead                      ; incr disable count
  968.          bgt.b    50$                                 ; >0, already disabled
  969.          ;
  970.          ;        If we're already processing an request, this one has to wait
  971.          ;        until that one is done, so go queue it.
  972.          ;
  973.          move.l   cr_IOReq(pc),d1                     ; have an active request?
  974.          bne.b    50$                                 ; yep, go queue this one
  975.          ;
  976.          ;        If we don't have enough bytes to satisfy this request then go
  977.          ;        queue it.
  978.          ;
  979.          cmp.l    i_InCnt(pc),d0                      ; length > current bytes?
  980.          bgt.b    50$                                 ; yep, go queue it
  981.          ;
  982.          ;        Setup fields and go copy the data
  983.          ;
  984.          move.l   IO_DATA(a1),cr_OutPtr               ; get/set output ptr
  985.          move.l   IO_LENGTH(a1),cr_Length             ; get/set output count
  986.          bsr      copyData                            ; go copy 'em
  987.          moveq    #0,d0                               ; I/O complete
  988.          ;
  989.          ;        We're done, so back off the disable counter.
  990.          ;
  991. 10$      subq.b   #1,disableRead                      ; decr disable count
  992.          ;
  993.          ;        Return to caller
  994.          ;
  995. 20$      rts                                          ; return
  996.          ;
  997.          ;        Just set flags and queue.  The read interrupt will handle it.
  998.          ;
  999. 50$      bset.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; indicate queued
  1000.          ;
  1001.          ;        Add this request to the end.
  1002.          ;
  1003.          DISABLE                                      ; disable interrupts
  1004.          lea.l    readQ(pc),a0                        ; get pointer to read queue
  1005.          move.l   a1,-(sp)                            ; save I/O request
  1006.          jsr      _LVOAddTail(a6)                     ; and queue it
  1007.          movea.l  (sp)+,a1                            ; restore I/O request
  1008.          ENABLE                                       ; enable interrupts
  1009.          ;
  1010.          ;        Indicate that this request was not handled immediatly.
  1011.          ;
  1012.          moveq    #1,d0                               ; I/O not complete
  1013.          bra.b    10$                                 ; branch to return
  1014.          ;
  1015.          ;        Process a CMD_WRITE request.
  1016.          ;
  1017. cmd_Write:
  1018.          clr.l    IO_ACTUAL(a1)                       ; clear bytes written
  1019.          move.l   IO_LENGTH(a1),d0                    ; get length and test
  1020.          beq.b    wbexit                              ; yep, leave
  1021.          ;
  1022.          ;        Entry point for Break command and fall through from cmd_Write.
  1023.          ;
  1024. sdcmd_Break:
  1025.          ;
  1026.          ;        Just set flags and queue. The TBE interrupt will handle it.
  1027.          ;
  1028.          bset.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; indicate queued
  1029.          ;
  1030.          ;        Protect.
  1031.          ;
  1032.          DISABLE                                      ; disable interrupts
  1033.          ;
  1034.          ;        Add request to end of queue.
  1035.          ;
  1036.          lea.l    writeQ(pc),a0                       ; get queue list ptr
  1037.          move.l   a1,-(sp)                            ; save I/O request
  1038.          jsr      _LVOAddTail(a6)                     ; and queue it
  1039.          movea.l  (sp)+,a1                            ; restore I/O request
  1040.          ;
  1041.          ;        If we have an active request, don't force interrupt.
  1042.          ;
  1043.          move.l   cw_IOReq(pc),d0                     ; have an active request?
  1044.          bne.b    10$                                 ; yep, branch
  1045.          ;
  1046.          ;        Force a TBE interrupt to get the writes going.
  1047.          ;
  1048.          move.w   #INTF_SETCLR|INTF_TBE,_intreq       ; make TBE pending
  1049.          ;
  1050.          ;        Enable, set RC and return to caller.
  1051.          ;
  1052. 10$      ENABLE                                       ; enable interrupts
  1053.          moveq    #1,d0                               ; I/O not complete
  1054. wbexit   rts                                          ; return
  1055.          ;
  1056.          ;        Resets serial read buffer
  1057.          ;
  1058.          ;        Since this routine is called internally, it must NOT reference
  1059.          ;        the I/O request.
  1060.          ;
  1061. cmd_Clear:
  1062.          DISABLE                                      ; disable interrupts
  1063.          ;
  1064.          ;        Load registers
  1065.          ;
  1066.          move.l   vb_CurRBuf(a5),d0                   ; get internal buffer ptr
  1067.          move.l   vb_CurRBufLen(a5),d1                ; and internal buffer len
  1068.          lea.l    i_BufPtr(pc),a0                     ; get ptr internal control
  1069.          ;
  1070.          ;        Initialize global buffer variables
  1071.          ;
  1072.          move.l   d0,(a0)+                            ; store buffer ptr
  1073.          move.l   d0,(a0)+                            ; set current input ptr
  1074.          move.l   d0,(a0)+                            ; set current output ptr
  1075.          add.l    d1,d0                               ; add buffer length
  1076.          move.l   d0,(a0)+                            ; store ptr to end of buffer
  1077.          clr.l    (a0)+                               ; clear byte cnt
  1078.          move.l   vb_CurBaud(a5),d0                   ; get internal baud
  1079.          lsr.l    #4,d0                               ; divide by 16
  1080.          sub.l    d0,d1                               ; subtract from length
  1081.          move.l   d1,(a0)                             ; set threshold
  1082.          ;
  1083.          ;        Enable, set RC and return.
  1084.          ;
  1085.          ENABLE                                       ; enable interrupts
  1086.          moveq    #0,d0                               ; I/O complete
  1087.          rts                                          ; return
  1088.          ;
  1089.          ;
  1090.          ;
  1091. cmd_Invalid
  1092.          move.b   #IOERR_NOCMD,IO_ERROR(a1)           ; set bad status
  1093.          moveq    #0,d0                               ; I/O complete
  1094.          rts                                          ; return
  1095.          ;
  1096.          ;        Returns number of bytes currently in internal buffer and
  1097.          ;        current serial port status.
  1098.          ;
  1099.          ;        NOTE:  Not completely compatible with standard serial.device
  1100.          ;        since it doesn't return the upper byte of IO_STATUS.
  1101.          ;
  1102. sdcmd_Query:
  1103.          DISABLE                                      ; disable interrupts
  1104.          moveq    #0,d0                               ; clear d0
  1105.          move.b   _ciabpra,d0                         ; get PR register
  1106.          andi.w   #~PRTMASK,d0                        ; zap printer bits
  1107.          ;
  1108.          ;        Uncomment the following to turn on the DSR bit.  This was done
  1109.          ;        for a user whose DSR pin did not function.
  1110.          ;
  1111. ;         bclr     #CIAB_COMDSR,d0                     ; set DSR
  1112.          ;
  1113.          ;
  1114.          ;
  1115.          move.w   d0,IO_STATUS(a1)                    ; store status
  1116.          move.l   i_InCnt(pc),IO_ACTUAL(a1)           ; byte left in buffer
  1117.          ;
  1118.          ;        Enable, set RC and return.
  1119.          ;
  1120.          ENABLE                                       ; enable interrupts
  1121.          moveq    #0,d0                               ; I/O complete
  1122.          rts                                          ; return
  1123.          ;
  1124.          ;
  1125.          ;
  1126. sdcmd_SetParams:
  1127.          ;
  1128.          ;        Validate the read, write, and stop bit lengths.
  1129.          ;
  1130.          moveq    #8,d0                               ; get char length
  1131.          cmp.b    IO_READLEN(a1),d0                   ; 8 bit chars for read?
  1132.          bne.b    40$                                 ; nope, branch
  1133.          cmp.b    IO_WRITELEN(a1),d0                  ; 8 bit chars for write?
  1134.          bne.b    40$                                 ; nope, branch
  1135.          moveq    #1,d0                               ; get stop bits
  1136.          cmp.b    IO_STOPBITS(a1),d0                  ; 1 stop bit?
  1137.          bne.b    40$                                 ; nope, branch
  1138.          ;
  1139.          ;        Get and validate the baud rate.
  1140.          ;
  1141.          move.l   IO_BAUD(a1),d1                      ; get baud from I/O req
  1142.          bne.b    20$                                 ; specified?
  1143.          move.l   vb_CurBaud(a5),d1                   ; get current baud from base
  1144.          bne.b    20$                                 ; specified?
  1145.          move.l   vb_DefBaud(a5),d1                   ; get default baud from base
  1146. 20$      cmpi.l   #110,d1                             ; too low?
  1147.          blt.b    40$                                 ; error
  1148.          cmpi.l   #292000,d1                          ; too high?
  1149.          bgt.b    40$                                 ; error
  1150.          ;
  1151.          ;        Get and validate the buffer length.
  1152.          ;
  1153.          move.l   IO_RBUFLEN(a1),d0                   ; get buffer length
  1154.          bne.b    30$                                 ; specified?
  1155.          move.l   vb_CurRBufLen(a5),d0                ; get current from base
  1156.          bne.b    30$                                 ; specified?
  1157.          move.l   vb_DefRBufLen(a5),d0                ; get default from base
  1158.          ;
  1159. 30$      bsr.b    internalReset                       ; go init baud and buffer
  1160. 35$      move.b   d0,IO_ERROR(a1)                     ; set error code
  1161.          bne.b    39$
  1162.          ;
  1163.          ;        If the 7wire bit is not on, we will only use 3-wire protocol
  1164.          ;
  1165.          moveq    #0,d0                               ; clear flag
  1166.          btst.b   #SERB_7WIRE,IO_SERFLAGS(a1)         ; use 7wire handshaking?
  1167.          beq.b    36$                                 ; nope, branch
  1168.          moveq    #1,d0                               ; set flag
  1169. 36$      move.b   d0,Handshake                        ; store flag
  1170.          ;
  1171.          ;        Set RC and return.
  1172.          ;
  1173. 39$      moveq    #0,d0                               ; I/O complete
  1174.          rts                                          ; return
  1175.          ;
  1176.          ;        Invalid parm detected.
  1177.          ;
  1178. 40$      moveq    #SerErr_InvParam,d0                 ; set error
  1179.          bra.b    35$                                 ; go return
  1180.          ;
  1181.          ;        Reset the buffer and baud rate
  1182.          ;
  1183.          ;        Registers:  D0 = Buffer length
  1184.          ;                    D1 = Baud rate
  1185.          ;
  1186. internalReset:
  1187.          ;
  1188.          ;        Disable interrupts.
  1189.          ;
  1190.          DISABLE                                      ; disable interrupts
  1191.          ;
  1192.          ;        Save buffer length and go set serper.
  1193.          ;
  1194.          move.l   d0,-(sp)                            ; save D0
  1195.          move.l   d1,d0                               ; get baud rate
  1196.          bsr.b    setPeriod                           ; go set the serper register
  1197.          move.l   (sp)+,d0                            ; restore D0
  1198.          ;
  1199.          ;        Determine if the buffer length is adequate for the selected CPS.
  1200.          ;        If not, use 64K for the length.
  1201.          ;
  1202.          move.l   vb_CurBaud(a5),d1                   ; get current baud
  1203.          lsr.l    #$3,d1                              ; divide by 8
  1204.          cmp.l    d1,d0                               ; buflen > CPS
  1205.          bhi.b    10$                                 ; yep, branch
  1206.          move.l   #65536,d0                           ; else use 64K
  1207.          ;
  1208. 10$      bsr.b    allocBuf                            ; go allocate a new buffer
  1209.          ;
  1210.          ;        Enable and return to caller.
  1211.          ;
  1212.          ENABLE                                       ; enable interrupts
  1213.          rts                                          ; return (D0 has status)
  1214.          ;
  1215.          ;        Set serial period register
  1216.          ;
  1217. setPeriod:
  1218.          cmp.l    vb_CurBaud(a5),d0                   ; current baud = new baud?
  1219.          beq.b    40$                                 ; yep, just exit
  1220.          move.l   d0,vb_CurBaud(a5)                   ; save new baud
  1221.          move.l   d0,d1                               ; save again
  1222.          lsl.l    #3,d0                               ; baud *= 8
  1223.          sub.l    d1,d0                               ; baud -= saved baud
  1224.          move.l   #25000000,d1                        ; get NTSC base
  1225.          cmpi.b   #50,PowerSupplyFrequency(a6)        ; PAL machine?
  1226.          bne.b    10$                                 ; nope, branch
  1227.          move.l   #24772416,d1                        ; get PAL base
  1228. 10$      cmpi.l   #$FFFF,d0                           ; Divide
  1229.          ble.b    20$                                 ;
  1230.          lsr.l    #5,d0                               ;
  1231.          divu.w   d0,d1                               ;
  1232.          andi.l   #$FFFF,d1                           ;
  1233.          lsr.l    #5,d1                               ;
  1234.          bra.b    30$                                 ;
  1235. 20$      divu.w   d0,d1                               ;
  1236. 30$      move.w   d1,_serper                          ; set period value
  1237. 40$      rts
  1238.          ;
  1239.          ;        Allocate new internal buffer
  1240.          ;
  1241. allocBuf:
  1242.          cmp.l    vb_CurRBufLen(a5),d0                ; len same as previous?
  1243.          beq.b    10$                                 ; yep, so no need to alloc
  1244.          move.l   d0,d1                               ; save length
  1245.          movem.l  d1/a1,-(sp)                         ; save registers
  1246.          moveq    #MEMF_PUBLIC,d1                     ; public memory
  1247.          jsr      _LVOAllocMem(a6)                    ; go allocate it
  1248.          movem.l  (sp)+,d1/a1                         ; restore registers
  1249.          tst.l    d0                                  ; did we get it?
  1250.          beq.b    20$                                 ; if zero, error
  1251.          bsr.b    freeBuf                             ; go free previous buffer
  1252.          move.l   d0,vb_CurRBuf(a5)                   ; store new ptr
  1253.          move.l   d1,vb_CurRBufLen(a5)                ; and length
  1254.          bsr      cmd_Clear                           ; go setup buffer
  1255. 10$      moveq    #0,d0                               ; success
  1256.          rts                                          ; return
  1257. 20$      moveq    #SerErr_BufErr,d0                   ; set error status
  1258.          rts                                          ; return
  1259.          ;
  1260.          ;        Free internal buffer
  1261.          ;
  1262. freeBuf:
  1263.          movem.l  d0-d1/a0-a1,-(sp)                   ; save registers
  1264.          move.l   vb_CurRBuf(a5),d0                   ; is one there?
  1265.          beq.b    10$                                 ; no so branch
  1266.          movea.l  d0,a1                               ; get ptr
  1267.          move.l   vb_CurRBufLen(a5),d0                ; get length
  1268.          clr.l    vb_CurRBuf(a5)                      ; clear
  1269.          clr.l    vb_CurRBufLen(a5)                   ; clear
  1270.          jsr      _LVOFreeMem(a6)                     ; free it
  1271. 10$      movem.l  (sp)+,d0-d1/a0-a1                   ; restore registers
  1272.          rts                                          ; return
  1273.          ;
  1274.          ;        Checks CTS status and if clear generates a TBE interrupt or
  1275.          ;        requeues the timer request.
  1276.          ;
  1277.          ;        Entered from Exec using the MsgPort callback.
  1278.          ;
  1279.          ;        Input:   a6 = ExecBase
  1280.          ;        Output:  none
  1281.          ;
  1282.          ;        No need to preserve d0/d1/a0/a1
  1283.          ;
  1284. timerRtn:
  1285.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  1286.          jsr      _LVORemove(a6)                      ; remove request
  1287.          ;
  1288.          ;        If we were breaking, reset adkcon.
  1289.          ;
  1290.          btst.b   #ADKB_UARTBRK,_adkconr              ; were we breaking?
  1291.          beq.b    10$                                 ; nope, skip reset
  1292.          ;
  1293.          move.w   #ADKF_UARTBRK,_adkcon               ; stop breaking
  1294.          ;
  1295.          ;
  1296.          ;
  1297. 10$      move.b   Handshake(pc),d0                    ; are we handshaking?
  1298.          beq.b    20$                                 ; nope, generate interrupt
  1299.          btst.b   #CIAB_COMCTS,_ciabpra               ; clear to send?
  1300.          beq.b    20$                                 ; yep, go start writing
  1301.          ;
  1302.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  1303.          move.l   #1000,IOTV_TIME+TV_MICRO(a1)        ; wait for .001 seconds
  1304.          jsr      _LVOSendIO(a6)                      ; go queue it
  1305.          bra.b    30$                                 ; branch to return
  1306.          ;
  1307.          ;        CTS is clear so generate TBE interrupt to restart writing
  1308.          ;
  1309. 20$      move.w   #INTF_SETCLR|INTF_TBE,_intreq       ; set TBE interrupt
  1310. 30$      rts                                          ; return
  1311.          ;
  1312.          ;        Non serial interrupt
  1313.          ;
  1314. level1n:
  1315.          movem.l  d0-d1/a0-a1/a5-a6,-(sp)             ; save registers
  1316.          lea      _custom,a0                          ; get ptr to custom regs
  1317.          move.w   intenar(a0),d1                      ; get enabled interrupts
  1318.          and.w    intreqr(a0),d1                      ; and in requested interrupts
  1319.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1320.          ;
  1321.          btst     #INTB_DSKBLK,d1                     ; Disk block done?
  1322.          beq.b    10$                                 ; nope, branch
  1323.          ;
  1324.          movem.l  IVDSKBLK(a6),a1/a5                  ; get data and code ptrs
  1325.          pea.l    20$(pc)                             ; push return address
  1326.          jmp      (a5)                                ; jump to routine
  1327.          ;
  1328. 10$      btst     #INTB_SOFTINT,d1                    ; software interrupt?
  1329.          beq.b    20$                                 ; nope, branch
  1330.          ;
  1331.          movem.l  IVSOFTINT(a6),a1/a5                 ; get data and code ptrs
  1332.          pea.l    20$(pc)                             ; push return address
  1333.          jmp      (a5)                                ; jump to routine
  1334.          ;
  1335. 20$      movem.l  (sp)+,d0-d1/a0-a1/a5-a6             ; restore registers
  1336.          rte                                          ; return
  1337.          ;
  1338.          ;        Level 1 interrupt handler
  1339.          ;
  1340. level1:
  1341.          btst.b   #INTB_INTEN,_intenar                ; interrupts enabled?
  1342.          beq.b    35$                                 ; nope, ignore
  1343.          btst.b   #INTB_SOFTINT,_intreqr+1            ; software interrupt?
  1344.          bne.b    level1n                             ; nope, branch
  1345.          btst.b   #INTB_TBE,_intreqr+1                ; xmit buffer empty?
  1346.          beq.b    level1n                             ; nope, invoke old handler
  1347.          ;
  1348.          ;        Handle "Transmit Buffer Empty" interrupt (write)
  1349.          ;
  1350.          move.w   #INTF_TBE,_intreq                   ; clear interrupt
  1351.          move.l   d0,-(sp)                            ; save D0 (faster than MOVEM)
  1352.          move.l   a0,-(sp)                            ; save A0 (faster than MOVEM)
  1353.          ;
  1354.          ;        If we're not handshaking, bypass it.
  1355.          ;
  1356. 10$      move.b   Handshake(pc),d0                    ; are we handshaking?
  1357.          beq.b    20$                                 ; nope, skip CTS test
  1358.          btst.b   #CIAB_COMCTS,_ciabpra               ; clear to send?
  1359.          bne.b    40$                                 ; nope, branch
  1360.          ;
  1361.          ;        If cw_Length goes negative here, we are either done with a
  1362.          ;        request or we were called as a result of a fake interrupt
  1363.          ;        to force us to get the next request going.
  1364.          ;
  1365. 20$      subq.l   #1,cw_Length                        ; decr write length
  1366.          blt.b    60$                                 ; < zero, done, branch
  1367.          ;
  1368.          ;        Currently processing a request.
  1369.          ;
  1370.          movea.l  cw_Buffer(pc),a0                    ; get buffer ptr
  1371.          move.w   #256,d0                             ; set stop bit
  1372.          move.b   (a0)+,d0                            ; get next byte
  1373.          move.l   a0,cw_Buffer                        ; store buffer ptr
  1374.          move.w   d0,_serdat                          ; store in serdat reg
  1375.          ;
  1376. 30$      movea.l  (sp)+,a0                            ; restore registers
  1377.          move.l   (sp)+,d0                            ; restore registers
  1378. 35$      rte                                          ; return
  1379.          ;
  1380.          ;        Queue a timer request to recheck CTS status
  1381.          ;
  1382. 40$      movem.l  d1/a1/a6,-(sp)                      ; save registers
  1383.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  1384.          move.l   #1000,IOTV_TIME+TV_MICRO(a1)        ; wait for .001 seconds
  1385.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1386.          jsr      _LVOSendIO(a6)                      ; queue the request
  1387.          movem.l  (sp)+,d1/a1/a6                      ; restore registers
  1388.          bra.b    30$                                 ; go return
  1389.          ;
  1390.          ;        There aren't anymore requests, so clear and exit
  1391.          ;
  1392. 50$      clr.l    cw_Length-Start(a6)                 ; clear length
  1393.          clr.l    cw_IOReq-Start(a6)                  ; clear
  1394.          movem.l  (sp)+,d1/a1/a6                      ; restore registers
  1395.          bra.b    30$                                 ; go return
  1396.          ;
  1397.          ;        Write request completed
  1398.          ;
  1399. 60$      movem.l  d1/a1/a6,-(sp)                      ; save registers
  1400.          ;
  1401.          move.l   cw_IOReq(pc),d0                     ; active I/O request?
  1402.          beq.b    70$                                 ; nope, branch
  1403.          ;
  1404.          ;        Reply it and setup for next
  1405.          ;
  1406.          movea.l  d0,a1                               ; get I/O request
  1407.          bclr.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; no longer active
  1408.          clr.b    IO_ERROR(a1)                        ; no error
  1409.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1410.          DEBUGIO  replyIO
  1411.          jsr      _LVOReplyMsg(a6)                    ; return I/O request
  1412.          ;
  1413. 70$      lea.l    Start(pc),a6                        ; get section base
  1414.          ;
  1415.          lea.l    writeQ(pc),a1                       ; get ptr to write queue
  1416.          move.l   (a1),a0                             ; get head of list
  1417.          move.l   (a0),d0                             ; get successor
  1418.          beq.b    50$                                 ; end of list? yep, branch
  1419.          ;
  1420.          ;        Remove the node from the list
  1421.          ;
  1422.          move.l   d0,(a1)                             ; make new head
  1423.          exg.l    d0,a0                               ; swap nodes
  1424.          move.l   a1,LN_PRED(a0)                      ; store predecessor
  1425.          ;
  1426.          move.l   d0,a1                               ; get I/O request
  1427.          ;
  1428.          ;        If it's a BREAK, then branch to process as such.
  1429.          ;
  1430.          cmpi.w   #SDCMD_BREAK,IO_COMMAND(a1)         ; BREAK command?
  1431.          beq.b    100$                                ; yep, branch
  1432.          ;
  1433.          ;        Check for absolute length
  1434.          ;
  1435.          move.l   IO_DATA(a1),a0                      ; get data ptr
  1436.          moveq    #-1,d1                              ; get value
  1437.          move.l   IO_LENGTH(a1),d0                    ; get length
  1438.          cmp.l    d1,d0                               ; length = -1?
  1439.          bne.b    90$                                 ; nope, skip scan
  1440.          ;
  1441.          ;        Scan the data for null to calc the length
  1442.          ;
  1443.          move.l   a0,d1                               ; save data ptr
  1444. 80$      tst.b    (a0)+                               ; does it equal 0?
  1445.          bne.b    80$                                 ; nope, so continue
  1446.          suba.l   d1,a0                               ; calc # of bytes+1
  1447.          move.l   a0,d0                               ; xfer
  1448.          subq.l   #1,d0                               ; calc # of bytes
  1449.          movea.l  d1,a0                               ; get data ptr
  1450.          ;
  1451. 90$      move.l   d0,IO_ACTUAL(a1)                    ; go ahead and set it
  1452.          bclr.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; no longer queued
  1453.          bset.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; make it active
  1454.          move.l   d0,cw_Length-Start(a6)              ; store length
  1455.          move.l   a0,cw_Buffer-Start(a6)              ; store buffer ptr
  1456.          move.l   a1,cw_IOReq-Start(a6)               ; store I/O request ptr
  1457.          ;
  1458.          movem.l  (sp)+,d1/a1/a6                      ; restore registers
  1459.          bra      10$                                 ; go start request
  1460.          ;
  1461.          ;        Start the BREAK.
  1462.          ;
  1463. 100$     bclr.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; no longer queued
  1464.          bset.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; make it active
  1465.          clr.l    cw_Length-Start(a6)                 ; clear length
  1466.          move.l   a1,cw_IOReq-Start(a6)               ; store I/O request ptr
  1467.          move.w   #ADKF_SETCLR|ADKF_UARTBRK,_adkcon   ; start break
  1468.          move.l   IO_BRKTIME(a1),d0                   ; get break time
  1469.          lea.l    timerReq(pc),a1                     ; get ptr to timer request
  1470.          move.l   d0,IOTV_TIME+TV_MICRO(a1)           ; set the timeout
  1471.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1472.          jsr      _LVOSendIO(a6)                      ; queue the request
  1473.          movem.l  (sp)+,d1/a1/a6                      ; restore registers
  1474.          bra      30$                                 ; go exit
  1475.          ;
  1476.          ;        Non serial interrupt
  1477.          ;
  1478. level5n:
  1479.          movem.l  d0-d1/a0-a1/a5-a6,-(sp)             ; save registers
  1480.          lea      _custom,a0                          ; get ptr to custom regs
  1481.          move.w   intenar(a0),d1                      ; get enabled interrupts
  1482.          and.w    intreqr(a0),d1                      ; and in requested interrupts
  1483.          movea.l  SysBase(pc),a6                      ; get ExecBase
  1484.          btst     #INTB_DSKSYNC,d1                    ; Disk synchronized?
  1485.          beq.b    10$                                 ; nope, branch
  1486.          movem.l  IVDSKSYNC(A6),a1/a5                 ; get data and code ptrs
  1487.          jsr      (a5)                                ; branch to routine
  1488. 10$      movem.l  (sp)+,d0-d1/a0-a1/a5-a6             ; restore registers
  1489.          rte                                          ; return
  1490.          ;
  1491.          ;        Default Level 5 handler
  1492.          ;
  1493. level5:
  1494.          btst.b   #INTB_INTEN,_intenar                ; interrupts enabled?
  1495.          beq.b    45$                                 ; nope, ignore
  1496.          btst.b   #INTB_RBF,_intreqr                  ; receive buffer full?
  1497.          beq.b    level5n                             ; nope, invoke old handler
  1498.          ;
  1499.          move.l   a0,-(sp)                            ; save registers
  1500.          ;
  1501. 10$      btst.b   #7,_serdatr                         ; Overrun?
  1502.          bne.b    50$                                 ; yep, branch
  1503.          ;
  1504. 20$      movea.l  i_BufIn(pc),a0                      ; get current ptr
  1505.          move.b   _serdatr+1,(a0)+                    ; store received byte
  1506.          move.w   #INTF_RBF,_intreq                   ; clear RBF interrupt
  1507.          addq.l   #1,i_InCnt                          ; incr bytes in buffer
  1508.          ;
  1509.          cmpa.l   i_BufEnd(pc),a0                     ; hit end of buffer?
  1510.          beq.b    60$                                 ; yep, branch
  1511. 30$      move.l   a0,i_BufIn                          ; store input ptr
  1512.          ;
  1513.          subq.l   #1,i_Thresh                         ; close to full buffer?
  1514.          beq.b    70$                                 ; yep, branch
  1515.          ;
  1516. 40$      btst.b   #INTB_RBF,_intreqr                  ; receive buffer full?
  1517.          bne.b    10$                                 ; yep, go get another byte
  1518.          ;
  1519.          movea.l  (sp)+,a0                            ; restore registers
  1520. 45$      rte                                          ; return
  1521.          ;
  1522.          ;        We've missed some data, so set overrun flag.
  1523.          ;
  1524. 50$      addq.b   #1,Overrun                          ; set overrun flag
  1525.          bra.b    20$                                 ; continue
  1526.          ;
  1527.          ;        Hit physical end of buffer, so wrap to the start of the buffer.
  1528.          ;
  1529. 60$      movea.l  i_BufPtr(pc),a0                     ; get buffer ptr
  1530.          bra.b    30$                                 ; continue
  1531.          ;
  1532.          ;        Hit buffer threshold, so tell other end not to send any more
  1533.          ;        data.
  1534.          ;
  1535. 70$      tst.b    Handshake                           ; are we handshaking?
  1536.          beq.b    40$                                 ; nope, skip RTS
  1537.          bset.b   #CIAB_COMRTS,_ciabpra               ; block further input
  1538.          bra.b    40$                                 ; go return
  1539.          ;
  1540.          ;
  1541.          ;
  1542. level2:
  1543.          ;
  1544.          ;        If there's nothing in the buffer, there's no point in going
  1545.          ;        any further.
  1546.          ;
  1547.          move.l   i_InCnt(pc),d0                      ; anything in the buffer?
  1548.          bne.b    20$                                 ; yep, branch
  1549. 10$      moveq    #0,d0                               ; set Z flag
  1550.          rts                                          ; return
  1551.          ;
  1552.          ;        If we've been "disabled" then get out.
  1553.          ;
  1554. 20$      move.b   disableRead(pc),d0                  ; internally disabled?
  1555.          bge.b    10$                                 ; yep, get out of here
  1556.          lea.l    Start(pc),a5                        ; get base
  1557.          ;
  1558.          ;        If we have an active request, branch down and try to fulfill it.
  1559.          ;
  1560.          move.l   cr_IOReq(pc),d0                     ; get and test active I/O
  1561.          bne.b    30$                                 ; nzero, active, branch
  1562.          ;
  1563.          ;        Get first node in list and test if empty.
  1564.          ;
  1565.          move.l   (a1),a0                             ; get head of list
  1566.          move.l   (a0),d0                             ; get successor
  1567.          beq.b    10$                                 ; end of list? yep, branch
  1568.          ;
  1569.          ;        Remove the node from the list
  1570.          ;
  1571.          move.l   d0,(a1)                             ; make new head
  1572.          exg.l    d0,a0                               ; swap nodes
  1573.          move.l   a1,LN_PRED(a0)                      ; store predecessor
  1574.          ;
  1575.          ;        Setup fields for processing a read request
  1576.          ;
  1577.          movea.l  d0,a1                               ; get I/O request
  1578.          bclr.b   #IOSERB_QUEUED,IO_FLAGS(a1)         ; no longer queued
  1579.          bset.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; make it active
  1580.          move.l   a1,cr_IOReq-Start(a5)               ; store I/O request
  1581.          move.l   IO_DATA(a1),cr_OutPtr-Start(a5)     ; get/set output ptr
  1582.          move.l   IO_LENGTH(a1),cr_Length-Start(a5)   ; get/set output count
  1583.          ;
  1584.          ;        Process an active I/O request
  1585.          ;
  1586. 30$      movea.l  SysBase(pc),a6                      ; get ExecBase
  1587.          move.l   d0,a1                               ; get I/O request
  1588.          bsr      copyData                            ; go copy 'em
  1589.          tst.l    d0                                  ; done with request?
  1590.          beq.b    10$                                 ; nope, branch
  1591.          ;
  1592.          ;        the request has been satisfied, so return it.
  1593.          ;
  1594.          clr.l    cr_IOReq-Start(a5)                  ; clear request
  1595.          bclr.b   #IOSERB_ACTIVE,IO_FLAGS(a1)         ; no longer active
  1596.          DEBUGIO  replyIO
  1597.          jsr      _LVOReplyMsg(a6)                    ; return I/O
  1598.          bra.b    10$
  1599.          ;
  1600.          ;        Registers:
  1601.          ;        Entry:   A1       Ptr to I/O Request
  1602.          ;                 A6       ExecBase
  1603.          ;        Exit:    D0       ZERO - request not done, do not reply it
  1604.          ;                          NZERO - request done, reply it
  1605.          ;
  1606. copyData:
  1607.          ;
  1608.          ;        Process an active I/O request (or fall through from above)
  1609.          ;
  1610.          movem.l  d2-d5/a1-a5,-(sp)                   ; save registers
  1611.          lea.l    Start(pc),a5                        ; get base
  1612.          movea.l  a1,a4                               ; get I/O request
  1613.          ;
  1614.          movea.l  i_BufOut(pc),a2                     ; get current bufout ptr
  1615.          movea.l  cr_OutPtr(pc),a3                    ; get current output ptr
  1616.          move.l   cr_Length(pc),d2                    ; get current bytes needed
  1617.          move.l   i_InCnt(pc),d3                      ; get current bytes in buffer
  1618.          ;
  1619.          ;        If we don't have enough bytes to satisfy the request,
  1620.          ;        set the length to the number of bytes we do have.
  1621.          ;
  1622.          cmp.l    d2,d3                               ; enuf to satisfy request?
  1623.          bge.b    15$                                 ; yep, so branch
  1624.          move.l   d3,d2                               ; # to copy = # in buffer
  1625.          bra.b    15$                                 ; branch to loop entry
  1626.          ;
  1627.          ;        Start of copy loop.
  1628.          ;
  1629. 10$      movea.l  i_BufPtr(pc),a2                     ; reset bufout to start
  1630.          ;
  1631.          ;        Entry point of copy loop.
  1632.          ;
  1633. 15$      move.l   d2,d3                               ; xfer # of bytes to copy
  1634.          ;
  1635.          ;        If the copy will extend past the end of the buffer, we can
  1636.          ;        only copy the number of bytes to the end this go around.
  1637.          ;
  1638.          move.l   i_BufEnd(pc),d0                     ; get ptr to end of buf
  1639.          sub.l    a2,d0                               ; calc # of bytes to end
  1640.          cmp.l    d0,d3                               ; # to copy < # to end?
  1641.          blt.b    20$                                 ; yep, branch
  1642.          move.l   d0,d3                               ; get bytes to end
  1643.          ;
  1644.          ;        Registers:
  1645.          ;
  1646.          ;        A2 = pointer from which data will be copied
  1647.          ;        A3 = pointer to which data will be copied
  1648.          ;        D2 = number of bytes that need to be copied
  1649.          ;        D3 = number of bytes to copy this iteration
  1650.          ;
  1651. 20$      btst.b   #SERB_EOFMODE,IO_SERFLAGS(a4)       ; EOFMODE requested?
  1652.          beq.b    30$                                 ; nope, just go copy
  1653.          ;
  1654.          ;        EOFMODE was specified so copy characters 1 at a time until
  1655.          ;        we hit an EOF character, the output butter has filled, or
  1656.          ;        the input buffer has drained.
  1657.          ;
  1658.          move.l   d3,d0                               ; get length
  1659.          ;
  1660. 21$      move.b   (a2)+,d1                            ; get byte
  1661.          move.b   d1,(a3)+                            ; put in output buffer
  1662.          ;
  1663.          lea.l    IO_TERMARRAY(a4),a1                 ; get termarry ptr
  1664.          cmp.b    (a1)+,d1                            ; found term char?
  1665.          bge.b    22$                                 ; possibly, branch
  1666.          cmp.b    (a1)+,d1                            ; found term char?
  1667.          bge.b    22$                                 ; possibly, branch
  1668.          cmp.b    (a1)+,d1                            ; found term char?
  1669.          bge.b    22$                                 ; possibly, branch
  1670.          cmp.b    (a1)+,d1                            ; found term char?
  1671.          bge.b    22$                                 ; possibly, branch
  1672.          cmp.b    (a1)+,d1                            ; found term char?
  1673.          bge.b    22$                                 ; possibly, branch
  1674.          cmp.b    (a1)+,d1                            ; found term char?
  1675.          bge.b    22$                                 ; possibly, branch
  1676.          cmp.b    (a1)+,d1                            ; found term char?
  1677.          bge.b    22$                                 ; possibly, branch
  1678.          cmp.b    (a1)+,d1                            ; found term char?
  1679.          bgt.b    23$                                 ; nope, branch
  1680. 22$      beq.b    24$                                 ; term char found?
  1681.          ;
  1682.          ;        Didn't find a term character, so continue with the copy loop
  1683.          ;
  1684. 23$      subq.l   #1,d0                               ; decr length counter
  1685.          bne.b    21$                                 ; continue if more
  1686.          bra.b    40$                                 ; done with copy, branch
  1687.          ;
  1688.          ;        We've found a termination character.
  1689.          ;
  1690. 24$      clr.l    cr_Length-Start(a5)                 ; done with request
  1691.          bra.b    50$                                 ; branch
  1692.          ;
  1693.          ;        EOFMODE not specified, so just do a bulk copy.
  1694.          ;
  1695.          ;        XXX POSSIBLE SPEEDUP XXX
  1696.          ;
  1697.          ;        For short copies it would be quicker to have a simple inline
  1698.          ;        loop, but what's short???  It would be different by CPU.
  1699.          ;
  1700. 30$      move.l   d3,d0                               ; get length
  1701.          movea.l  a3,a1                               ; where to put it
  1702.          movea.l  a2,a0                               ; where to get it
  1703.          jsr      _LVOCopyMem(a6)                     ; copy it
  1704.          adda.l   d3,a2                               ; update bufout
  1705.          adda.l   d3,a3                               ; update outptr
  1706.          ;
  1707.          ;        Fall through and entered from EOFMODE loop
  1708.          ;
  1709.          ;        If the following calculation results in a value greater than
  1710.          ;        zero, then we have a buffer wrap and need to process the
  1711.          ;        remaining bytes at the beginning of the buffer.
  1712.          ;
  1713. 40$      sub.l    d3,d2                               ; calc bytes left to copy
  1714.          bgt      10$                                 ; >0, more to copy, branch
  1715.          ;
  1716.          ;
  1717.          ;
  1718. 50$      move.l   a3,d1                               ; get outptr
  1719.          sub.l    cr_OutPtr(pc),d1                    ; calc length
  1720.          move.l   a3,cr_OutPtr-Start(a5)              ; update outptr
  1721.          ;
  1722.          ;        Update output ptr and I/O request
  1723.          ;
  1724.          move.l   a2,i_BufOut-Start(a5)               ; store bufout ptr
  1725.          add.l    d1,IO_ACTUAL(a4)                    ; update I/O request
  1726.          ;
  1727.          ;        Update number of bytes left in the buffer.
  1728.          ;
  1729.          sub.l    d1,i_InCnt-Start(a5)                ; calc bytes left in buffer
  1730.          ;
  1731.          ;        If the threshold becomes positive here, then, if requested,
  1732.          ;        tell the other end that it's okay to start sending more data.
  1733.          ;
  1734.          add.l    d1,i_Thresh-Start(a5)               ; calc thresh and test
  1735.          ble.b    60$                                 ; <= 0, need more data, skip
  1736.          tst.b    Handshake-Start(a5)                 ; are we handshaking?
  1737.          beq.b    60$                                 ; nope, skip RTS
  1738.          bclr.b   #CIAB_COMRTS,_ciabpra               ; ready to receive more data
  1739.          ;
  1740.          ;        Set error if we've had any overruns.
  1741.          ;
  1742. 60$      tst.b    Overrun-Start(a5)                   ; did overrun occur?
  1743.          beq.b    70$                                 ; nope, branch
  1744.          clr.b    Overrun-Start(a5)                   ; reset overrun flag
  1745.          move.b   #SerErr_LineErr,IO_ERROR(a4)        ; set error code
  1746.          ;
  1747.          ;        Calc number of bytes left to copy.  If the result is greater
  1748.          ;        than zero, then we have more to copy so return an incomplete
  1749.          ;        status.
  1750.          ;
  1751. 70$      moveq    #0,d0                               ; assume I/O incomplete
  1752.          sub.l    d1,cr_Length-Start(a5)              ; update length and test
  1753.          bgt.b    90$                                 ; >0, more to do, branch
  1754.          ;
  1755.          ;        We've completed the I/O request either by copying the requested
  1756.          ;        of bytes or by finding an EOFMODE character, so return a "reply"
  1757.          ;        status.
  1758.          ;
  1759.          moveq    #1,d0                               ; indicate reply
  1760.          ;
  1761.          ;        Restore and exit
  1762.          ;
  1763. 90$      movem.l  (sp)+,d2-d5/a1-a5                   ; restore registers
  1764.          rts                                          ; return (status in D0)
  1765.          ;
  1766.          ;        Align data
  1767.          ;
  1768.          CNOP     0,4
  1769.          ;
  1770.          ;
  1771.          ;
  1772. Init:
  1773.          DC.L     sizeof_Base8n1
  1774.          DC.L     funcTab
  1775.          DC.L     dataTab
  1776.          DC.L     InitRoutine
  1777.          ;
  1778.          ;
  1779.          ;
  1780. funcTab:
  1781.          DC.W     -1
  1782.          DC.W     dev_Open-funcTab
  1783.          DC.W     dev_Close-funcTab
  1784.          DC.W     dev_Expunge-funcTab
  1785.          DC.W     dev_Null-funcTab
  1786.          DC.W     dev_BeginIO-funcTab
  1787.          DC.W     dev_AbortIO-funcTab
  1788.          DC.W     -1
  1789.          ;
  1790.          ;
  1791.          ;
  1792. dataTab:
  1793.          INITBYTE LN_TYPE,NT_DEVICE
  1794.          INITLONG LN_NAME,Name
  1795.          INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
  1796.          INITWORD LIB_VERSION,VERSION
  1797.          INITWORD LIB_REVISION,REVISION
  1798.          INITLONG LIB_IDSTRING,IdString
  1799.          DC.W     0
  1800.          ;
  1801.          ;        String Constants
  1802.          ;
  1803. miscresource:
  1804.          DC.B     "misc.resource",0
  1805. timerdevice:
  1806.          DC.B     "timer.device",0
  1807. intuitlib:
  1808.          DC.B     "intuition.library",0
  1809. Name:
  1810.          DC.B     "8n1.device",0
  1811. IdString:
  1812.          VSTRING
  1813.          ;
  1814.          ;        End of checksummed area.  (Realigns data too!)
  1815.          ;
  1816. ENDTag:
  1817.          CNOP     0,4
  1818.          ;
  1819.          ;        Global SysBase (Use instead of AbsExecBase for speed)
  1820.          ;
  1821. SysBase:
  1822.          DC.L     0
  1823.          ;
  1824.          ;        Internal buffer tracking (DO NOT CHANGE THE ORDER!!!!)
  1825.          ;
  1826. i_BufPtr:
  1827.          DC.L     0
  1828. i_BufIn:
  1829.          DC.L     0
  1830. i_BufOut:
  1831.          DC.L     0
  1832. i_BufEnd:
  1833.          DC.L     0
  1834. i_InCnt:
  1835.          DC.L     0
  1836. i_Thresh:
  1837.          DC.L     0
  1838.          ;
  1839.          ;        Used while processing a read request.
  1840.          ;
  1841. cr_IOReq:
  1842.          DC.L     0
  1843. cr_OutPtr:
  1844.          DC.L     0
  1845. cr_Length:
  1846.          DC.L     0
  1847.          ;
  1848.          ;        List head for read requests
  1849.          ;
  1850. readQ:
  1851.          DC.L     readQ+MLH_TAIL
  1852.          DC.L     0
  1853.          DC.L     readQ
  1854.          ;
  1855.          ;        Write control.
  1856.          ;
  1857. cw_Length:
  1858.          DC.L     0
  1859. cw_Buffer:
  1860.          DC.L     0
  1861. cw_IOReq:
  1862.          DC.L     0
  1863.          ;
  1864.          ;        List head for write requests
  1865.          ;
  1866. writeQ:
  1867.          DC.L     writeQ+MLH_TAIL
  1868.          DC.L     0
  1869.          DC.L     writeQ
  1870.          ;
  1871.          ;
  1872.          ;
  1873. timerPort:
  1874.          DC.L     0                                   ; LN_SUCC
  1875.          DC.L     0                                   ; LN_PRED
  1876.          DC.B     NT_MSGPORT                          ; LN_TYPE
  1877.          DC.B     0                                   ; LN_PRI
  1878.          DC.L     0                                   ; LN_NAME
  1879.          DC.B     3                                   ; MP_FLAGS (undoc'ed)
  1880.          DC.B     0                                   ; MP_SIGBIT
  1881.          DC.L     timerRtn                            ; MP_SIGTASK
  1882.          DC.L     timerPort+MP_MSGLIST+LH_TAIL        ; LH_HEAD
  1883.          DC.L     0                                   ; LH_TAIL
  1884.          DC.L     timerPort+MP_MSGLIST                ; LH_TAILPRED
  1885.          DC.B     0                                   ; LH_TYPE
  1886.          DC.B     0                                   ; LH_pad
  1887.          DC.W     0                                   ; long align
  1888.          ;
  1889.          ;
  1890.          ;
  1891. timerReq:
  1892.          DC.L     0                                   ; LN_SUCC
  1893.          DC.L     0                                   ; LN_PRED
  1894.          DC.B     NT_MESSAGE                          ; LN_TYPE
  1895.          DC.B     0                                   ; LN_PRI
  1896.          DC.L     0                                   ; LN_NAME
  1897.          DC.L     timerPort                           ; MN_REPLYPORT
  1898.          DC.W     IOTV_SIZE                           ; MN_LENGTH
  1899.          DC.L     0                                   ; IO_DEVICE
  1900.          DC.L     0                                   ; IO_UNIT
  1901.          DC.W     TR_ADDREQUEST                       ; IO_COMMAND
  1902.          DC.B     0                                   ; IO_FLAGS
  1903.          DC.B     0                                   ; IO_ERROR
  1904.          DC.L     0                                   ; TV_SECS
  1905.          DC.L     0                                   ; TV_MICROS
  1906.          ;
  1907.          ;
  1908.          ;
  1909. VBInterrupt:
  1910.          DC.L     0                                   ; LN_SUCC
  1911.          DC.L     0                                   ; LN_PRED
  1912.          DC.B     NT_INTERRUPT                        ; LN_TYPE
  1913.          DC.B     0                                   ; LN_PRI
  1914.          DC.L     Name                                ; LN_NAME
  1915.          DC.L     readQ                               ; IS_DATA
  1916.          DC.L     level2                              ; IS_CODE
  1917.          ;
  1918.          ;        Global flags
  1919.          ;
  1920. Overrun:
  1921.          DC.B     0
  1922. Handshake:
  1923.          DC.B     1
  1924. disableRead:
  1925.          DC.B     -1
  1926.          ;
  1927.          ;
  1928.          ;
  1929.          END
  1930.  
  1931.